package com.feiyun.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.feiyun.common.PageParam;
import com.feiyun.config.WeChatUtil;
import com.feiyun.exception.ServiceException;
import com.feiyun.interceptor.RedisEnum;
import com.feiyun.mapper.UserMapper;
import com.feiyun.mapper.UserPhotoMapper;
import com.feiyun.mapper.WxUserLoginMapper;
import com.feiyun.model.dto.UserConditionDto;
import com.feiyun.model.dto.WeChatPhoneDTO;
import com.feiyun.model.entity.User;
import com.feiyun.model.entity.UserPhoto;
import com.feiyun.service.IUserService;
import com.feiyun.util.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import static com.feiyun.exception.ExceptionTypeEnum.SELECT_TIME_OVER_EXCEPTION_TYPE;

/**
 * @ClassName UserServiceImpl
 * @author: xingming
 * @Description:
 * @time 2023/03/12 17:27:21
 * @Version 1.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements IUserService {
    private final UserMapper userMapper;

    private final UserPhotoMapper userPhotoMapper;

    private final JWTUtils jwtUtils;

    private final static Integer SELECT_TIMES = 1;

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private final WxUserLoginMapper wxUserLoginMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public User register(User user) {
        user.setUuid(UUIDUtils.generate32UUID());
        //创建时间
        user.setCreateTime(LocalDateUtils.getNowDate());
        //允许通过
        user.setIsApproved(true);
        this.updateUserYearInfo(user);
        userMapper.updateById(user);

        // user.setToken(jwtUtils.createToken(user.getId()));
        return user;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteByUserId(int id) {
        // 1、 确定逻辑删除还是物理删除
        // 2、 接口是否能服用
        // 3、 照片表和上传关系表数据也得清除
        QueryWrapper<UserPhoto> userPhotoQueryWrapper = new QueryWrapper();
        userPhotoQueryWrapper.eq("user_id",id);
        int deleteValue = userPhotoMapper.delete(userPhotoQueryWrapper);
        log.info("用户id：{}，清理照片{}张",id,deleteValue);

        int i = userMapper.deleteById(id);
        log.info("物理删除id：{}用户信息",id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUser(User user) {
        if (user.getBirthDay() != null) {
            this.updateUserYearInfo(user);
        }
        userMapper.updateById(user);
    }

    public void updateUserYearInfo(User user){
        user.setAge(DateUtils.getAgeByBirth(user.getBirthDay()));
        user.setConstellation(DateUtils.getConstellation(user.getBirthDay()));
        user.setZodiac(DateUtils.getZodica(user.getBirthDay()));
    }

    /**
     * 条件查询
     *
     * @param conditionDto 条件查询实体
     * @return 符合条件的用户
     */
    @Override
//    @Cacheable(value = "user", key = "'selectAll'")
    public Page<User> selectUserByCondition(PageParam<UserConditionDto> conditionDto) {
        Page<User> page = new Page((long)conditionDto.getPageNum(), (long)conditionDto.getPageSize());
        QueryWrapper<User> wrapper = new QueryWrapper();
        wrapper.eq("is_approved", true);
        UserConditionDto param = (UserConditionDto)conditionDto.getParam();
        wrapper.eq(param.getGender() != null, "gender", param.getGender());
        wrapper.eq(param.getIsDivorced() != null, "is_divorced", param.getIsDivorced());
        wrapper.between(param.getStartAge() != null && param.getEndAge() != null, "age", param.getStartAge(), param.getEndAge());
        wrapper.orderByDesc("id");
        Page<User> userPage = (Page)this.userMapper.selectPage(page, wrapper);
        List<User> userList = userPage.getRecords();
        Collections.shuffle(userList);
        userList.forEach((user) -> {
            user.setName(DataDesensitizedUtils.desensitizedName(user.getName()));
        });
        return userPage;
    }

    @Override
    public Page<User> selectUser(PageParam<User> userPageParam) {
        Page<User> page = new Page<>(userPageParam.getPageNum(), userPageParam.getPageSize());
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        User param = userPageParam.getParam();
        // 查看审批未通过的
        wrapper.eq("is_approved", true);
        // 倒叙
        wrapper.orderByDesc("id");
        if (param != null){
            wrapper.eq(param.getUserId() != null, "user_id", param.getUserId());
            wrapper.like(param.getName() != null, "name", param.getName());
        }
        Page<User> userPage = userMapper.selectPage(page, wrapper);
        return userPage;
    }

    @Override
    public List<UserPhoto> selectPictureById(UserPhoto userPhoto) {
        QueryWrapper<UserPhoto> wrapper = new QueryWrapper();
        wrapper.eq("user_id",userPhoto.getUserId());
        wrapper.eq("is_avatar",userPhoto.getIsAvatar());
        List<UserPhoto> userPhotos = userPhotoMapper.selectList(wrapper);
        return userPhotos;
    }

    @Override
    public User wxlogin(WeChatPhoneDTO weChatPhone) {

        // 获取token
        String accessToken = WeChatUtil.getAccessToken();

        //根据code获取电话号
        JSONObject resultJson = WeChatUtil.getPhoneNumber(weChatPhone.getCode(), accessToken);
        // 都返回值进行判断
        String errcode = resultJson.getString("errcode");
        if ("40029".equals(errcode) || "-1".equals(errcode)){
            log.error("获取微信手机号失败。返回值为：{}",resultJson);
        }
        JSONObject phoneInfo = resultJson.getJSONObject("phone_info");
        String phoneNumber = phoneInfo.getString("phoneNumber");

        // 判断电话号是否存在
        QueryWrapper<User> wrapper = new QueryWrapper();
        wrapper.eq("phone_number",phoneNumber);
        List<User> UserList = userMapper.selectList(wrapper);
        if (UserList == null || UserList.size() == 0){
            // 不存在保留
            User user = new User();
            user.setPhoneNumber(phoneNumber);
            user.setUuid(UUIDUtils.generate32UUID());
            user.setCreateTime(LocalDateUtils.getNowDate());
            // 0 代表微信注册
            user.setSourceFrom("0");
            user.setIsApproved(false);
            user.setUserId(UUIDUtils.generate6UUID());
            userMapper.insert(user);
            return user;
        }
        return UserList.get(0);
        // 设置token
    }

    @Override
    public User getUserInfo(User user) {
        //如果id 查询就
        User userInfo = null;
        if (user.getId() != null){
            userInfo = userMapper.selectById(user.getId());
        }
        if (StringUtils.isNotBlank(user.getUserId())){
            QueryWrapper<User> userQueryWrapper = new QueryWrapper();
            userQueryWrapper.eq("user_id",user.getUserId());
            userInfo = userMapper.selectOne(userQueryWrapper);
        }
        if (userInfo != null){
            QueryWrapper<UserPhoto> wrapper = new QueryWrapper();
            wrapper.eq("user_id",userInfo.getId());
            wrapper.eq("is_avatar",false);
            List<UserPhoto> userPhotos = userPhotoMapper.selectList(wrapper);
            if (userPhotos != null || userPhotos.size() > 0){
                userInfo.setUserPhotosList(userPhotos);
            }
        }
        return userInfo;
    }

    @Override
    public Map<String, Integer> getUserCount(PageParam<UserConditionDto> conditionDto) {

        //TODO
        return null;
    }

    @Override
    public User wxGetUserInfo(UserConditionDto user) {
        Boolean isSelect = false;
        // 判断是否注册完成
        if (!user.getIsOverRegister()){
            // 去redis 获取 是否有值
            String redisKey = RedisKeyUtils.keyBuilder(RedisEnum.DMQX_NOAPPROVED_SELECT_TIMES, user.getSelfUserId().toString());
            //判断redis中是否存在，不存在就添加，存在就+1；
            if (redisUtil.hasKey(redisKey)){
                // 查询值
                Integer hasSelectTimes = (Integer)redisUtil.get(redisKey);
                if (hasSelectTimes >= 5){
                    //返回次数用完提示
                    throw new ServiceException(SELECT_TIME_OVER_EXCEPTION_TYPE);
                }else {
                    hasSelectTimes = hasSelectTimes + 1;
                    redisUtil.set(redisKey,hasSelectTimes,60 * 60 * 24 * 3);
                    isSelect = true;
                }
            }else {
                redisUtil.set(redisKey,SELECT_TIMES,60 * 60 * 24 * 3); // 设置过期时间3天
                isSelect = true;
            }
        }else {
            isSelect = true;
        }
        User otherUserInfo = null;
        if (isSelect){
            otherUserInfo = this.getUserInfo(new User(user.getOtherUserId()));
        }
        return otherUserInfo;
    }
}